import time
from playwright.sync_api import TimeoutError

from tool_class.exception_handling import exception_handling


class PageHandleBase:
    """ 页面的基础操作类 """
    current_position = None

    def __init__(self, page):
        self.page = page

    @exception_handling
    def upload_file(self, file_path):
        file_input_locator = self.page.locator('input[type="file"]')
        # 设置要上传的文件路径
        file_input_locator.set_input_files(file_path)

    @exception_handling
    def pull_text_checked(self,external_ID, testId, text = None,li_text = None):
        """
        :param :param testId: 外部ID，用于定位外层框的元素
        :param testId: 下拉选项testId，模糊匹配，完整ID:monitor-alarm-t1-0 模糊匹配:monitor-alarm-t1
        :param text: 下拉选项的文本
        :param li_text: 下拉多选项的文本列表
        :return:
        """
        self.page.get_by_test_id(external_ID).click()
        if li_text:
            text_list = []
            for tag in li_text:
                elements = self.page.locator(f'[data-testid*="{testId}"]')
                for element in elements.all():
                    if element.inner_text() == f"{tag}":
                        text_list.append(element.inner_text())
                        element.locator('span').first.click()
            if len(text_list) == 1:  # 如果只有一个值，则返回单个值
                return text_list[0]
            return text_list
        text_element = self.page.locator(f'[data-testid*="{testId}"]:has-text("{text}")')
        # text_element = elements.get_by_text(f"{text}")
        text_element.click()
        return text_element.inner_text()

    @exception_handling
    def pull_checkbox(self, testId, li_lsit):
        """
        testId (str): 测试ID，用于定位并点击的元素。外层框的testId
        li_lsit (list): 下拉列表中需要多选的testId ['ID','ID']
        :return: 返回多选后的值
        """
        self.page.get_by_test_id(testId).click()
        text_list = []
        for li_element in li_lsit:
            element_text = self.page.locator(f'li[data-testid="{li_element}"]').inner_text()
            element = self.page.locator(f'li[data-testid="{li_element}"]').locator('span').first
            element.click()
            text_list.append(element_text)
        if len(text_list) == 1:  # 如果只有一个值，则返回单个值
            return text_list[0]
        print(text_list)
        return text_list

    @exception_handling
    def pull_checked(self, testId, liId):
        """
        testId (str): 测试ID，用于定位并点击的元素。外层框的testId
        liId (str): 下拉列表中需要点击testId
        :return: 返回点击后的值
        """
        self.page.get_by_test_id(testId).click()
        li_value = self.page.get_by_test_id(liId).inner_text()
        self.page.get_by_test_id(liId).click()
        return li_value

    @exception_handling
    def pull_cascade(self, testId, title_lsit):
        """
        testId (str): 测试ID，用于定位并点击的元素。外层框的testId
        title_lsit (str): 下拉列表中需要级联的关系【'售后服务>click','服务流程>click','增值业务>click'】
        :return: 返回级联后的关系
        """
        self.page.get_by_test_id(testId).click()
        text_list = []
        for title in title_lsit:
            text, operation = title.split('>')
            element = self.page.locator(f'[role="menuitem"][title="{text}"]').first
            text_list.append(element.inner_text())
            if operation == 'checked':
                element.locator('span').first.click()
            elif operation == 'hover':
                element.hover()
            elif operation == 'click':
                element.click()
        if len(text_list) == 1:  # 如果只有一个值，则返回单个值
            return text_list[0]
        print(text_list)
        return text_list

    @exception_handling
    def input(self, testId, value):
        """
        testId (str): 测试ID，用于定位需要输入的input的testId
        value (str): 需要输入的值
        :return: 返回输入进去的值
        """
        input_element = self.page.locator(f'[data-testid="{testId}"]').locator('input').first
        if input_element.is_visible():
            input_element.fill(value)
            return input_element.get_attribute('value')
        else:
            input_element = self.page.locator(f'[data-testid="{testId}"]').locator('textarea').first
            input_element.fill(value)
            return input_element.get_attribute('value')

    @exception_handling
    def time_input(self, testId, start_time='', end_time='', closing_date=None, outer_testId=None,star_placeholder='开始日期', end_placeholder='结束日期'):
        """
        testId (str): 测试ID，用于定位需要输入的input的testId
        start_time (str): 开始时间
        end_time (str): 结束时间
        closing_date (str): 截止时间
        outer_testId (str): 测试ID，用于定位外层的testId
        """
        input_element = self.page.locator(f'[data-testid="{testId}"]')
        input_element.click()
        if closing_date:
            self.page.get_by_test_id(outer_testId).locator('span').first.click()
            input_element.locator('input[placeholder="请选择日期"]').fill(closing_date)
            input_element.locator('input[placeholder="请选择日期"]').click()
            input_element.locator('input[placeholder="请选择日期"]').press('Enter')
            return input_element.locator('input[placeholder="请选择日期"]').get_attribute('value')
        else:
            if star_placeholder and end_placeholder:
                input_element.locator(f'input[placeholder="{star_placeholder}"]').click()
                input_element.locator(f'input[placeholder="{star_placeholder}"]').fill(start_time)
                input_element.locator(f'input[placeholder="{end_placeholder}"]').click()
                input_element.locator(f'input[placeholder="{end_placeholder}"]').fill(end_time)
                input_element.locator(f'input[placeholder="{end_placeholder}"]').press('Enter')
                return [input_element.locator(f'input[placeholder="{star_placeholder}"]').get_attribute('value'),
                        input_element.locator(f'input[placeholder="{end_placeholder}"]').get_attribute('value')]

    @exception_handling
    def radio_select(self, testId, radio_vaules):
        """
        testId (str): 测试ID，用于定位需要点击外层的testId
        radio_vaules (list): 需要选择的值列表 【'补充','过滤'】
        :return: 返回选择的值
        """
        radio = self.page.get_by_test_id(testId)
        if isinstance(radio_vaules, list):
            vaules = []
            for vaule in radio_vaules:
                radio.get_by_text(vaule).click()
                vaules.append(radio.get_by_text(vaule).inner_text())
                return vaules
        if isinstance(radio_vaules, str):
            radio.get_by_text(radio_vaules).click()
            return radio.get_by_text(radio_vaules).inner_text()

    @exception_handling
    def button_click(self, testId=None, text=None):
        """
        testId (str): 测试ID，用于定位并点击按钮的testId
        text (str): 按钮的文本，用于文本定位
        :return: 返回点击按钮的值
        """
        if text:
            button = self.page.locator(f'button:has-text("{text}")')
            button_vaule = button.inner_text()
            button.click()
            return button_vaule
        vaule = self.page.get_by_test_id(testId).inner_text()
        self.page.get_by_test_id(testId).click()
        return vaule

    @exception_handling
    def checkbox(self, childId_list=None, parentId=None, is_clear=False):
        """
        parentId (str): 测试ID，用于当前第一级的testId,需要全选时获清空时传入
        childId_list (list): 需要多选的第一级下子元素的testId ['op-0','op-1']
        is_clear (bool): 是否需要清除选择，默认不清空
        :return: 返回多选后的值
        """
        vaules = []

        if parentId:
            calss_name = self.page.locator(f'[data-testid="{parentId}"]').get_attribute('class')
            if is_clear:
                if calss_name == 'arco-checkbox arco-checkbox-indeterminate':
                    self.page.get_by_test_id(parentId).dblclick()
                elif calss_name == 'arco-checkbox arco-checkbox-checked':
                    self.page.get_by_test_id(parentId).click()
            else:
                if calss_name != 'arco-checkbox arco-checkbox-checked':
                    self.page.get_by_test_id(parentId).click()
        if childId_list:
            for childId in childId_list:
                self.page.get_by_test_id(childId).click()
                vaules.append(self.page.get_by_test_id(childId).inner_text())
        return vaules
    @exception_handling
    def action_bar(self, text, testId):
        """
        获取整行数据
        :param text: 需要操作某一列的字段文本，来指定操作这列的操作栏按钮
        :param testId: 操作按钮testId，模糊匹配，完整ID:monitor-alarm-t1-0 模糊匹配:monitor-alarm-t1
        :return: 返回当前行数据
        """
        tr_element = self.page.locator(f'xpath=//*[text()="{text}"]//ancestor::tr[1]')
        tr_element.locator(f'[data-testid*="{testId}"]').click()
        tr_value_list = []
        for child in tr_element.locator('*').all():
            if child.text_content() not in tr_value_list:
                tr_value_list.append(child.text_content())
                print(child.text_content())
        return [itme.strip() for itme in tr_value_list]

    @exception_handling
    def get_values(self, key_value):
        """
        key_value (str): 用于或者字段文本和testId的字典，如：{'字段1':'testId1','字段2':'testId2'}
        :return: 返回对应关系的值
        """
        result = {}
        for key, value in key_value.items():
            result[key] = self.page.get_by_test_id(value).inner_text()
        return result

    @exception_handling
    def get_ul_value(self, testId):
        """
        testId (str): 测试ID，外层框的testId
        :return: 下拉框中的所有枚举值
        """
        # 通过testId模糊匹配所有的li元素
        elements = self.page.locator(f'[data-testid*="{testId}"]')
        if elements.count() != 0:
            # 获取下拉列表中所有的值，但第一个是标题，所以需要跳过
            value_list = [element.text_content() for element in elements.all()[1:]]
            return value_list
        else:
            return '暂无数据'

    @exception_handling
    def get_list_data(self, testId, page_number=None):
        """
        testId (str): 测试ID，用于匹配列表数据的testId，模糊匹配，完整ID:monitor-alarm-t1-0 模糊匹配:monitor-alarm-t1
        page_number (int): 需要获取的数据的页数，默认不传，获取当前页数据
        :return: 返回当前页数据
        """
        if page_number:
            self.page.locator('span[title="20 条/页"]').click()
            self.page.get_by_text(f'{page_number} 条/页').click()
        elements = self.page.locator(f'[data-testid*="{testId}"]')
        if elements.count() != 0:
            list_data = [element.text_content() for element in elements.all()]
            print(list_data)
            print(elements.count())
            return list_data
        else:
            return "暂无数据"
    @exception_handling
    def goto_local(self, local_path=None, url_path=None):
        """
        url_path (str): 需要跳转的路径，格式：'/ins/#/dataCenter/processing'
        local_path (str): 需要去到的页面的ID路径，格式：'ID1>ID2>ID3'
        :return: 返回是否成功
        """
        PageHandleBase.current_position = {"local_path":local_path, "url_path": url_path}
        try:
            if url_path:
                now_path = self.page.url
                if url_path not in now_path:
                    print('跳转路径')
                    self.page.goto(url_path)
            if local_path:
                if '>' not in local_path:
                    self.page.get_by_test_id(local_path).click()
                else:
                    path_list = local_path.split('>')
                    for path in path_list:
                        self.page.get_by_test_id(path).click()
            return True
        except TimeoutError:
            return False

    @exception_handling
    def close_pull(self, testId, name, deviation_value):
        element = self.page.locator(f'[data-testid*="{testId}"]'). \
            locator(f'xpath=//*[text()="{name}"]//ancestor::span[1]').first
        # print(element.get_attribute('class'), "--------------")
        bounding_box = element.bounding_box()
        x = bounding_box['x'] + bounding_box['width'] - deviation_value
        y = bounding_box['y'] + bounding_box['height'] / 2
        self.page.mouse.click(x, y)

    @exception_handling
    def element_click(self, testId,el_y=0):
        target_element = self.page.get_by_test_id(testId)
        if el_y:
            box = target_element.bounding_box()
            if box:
                above_y = box['y'] - el_y  # 根据实际情况调整这个偏移量
                self.page.mouse.click(box['x'], above_y)
        else:
            target_element.click()
        return True

    @exception_handling
    def get_element_index(self,testId,text):
        element_lsit = self.get_list_data(testId)
        return element_lsit.index(text)

def test_page(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/dataCenter/founding')
    page_obj.pull_text_checked('founding-dataSource-10002','founding-dataSource-10002-op',text = "本地上传")


def test_page_01(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/dataCenter/processing')
    session_page.get_by_test_id('processing-1002').click()
    session_page.get_by_test_id('processing-2003').first.click()
    page_obj.radio_select('processing-3005', ['补充', '过滤'])


"""founding-carseries-10003  founding-tabs-1003"""


def test_page_02(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/dataCenter/monitor')
    # session_page.get_by_test_id('founding-tabs-1003').click()
    # session_page.get_by_test_id('processing-2003').first.click()
    page_obj.pull_cascade('monitor-alarm-1002', ['小红书>checked'])
    # page_obj.pull_checkbox('founding-carseries-10001',
    #                        ['founding-carseries-10001-op-0', 'founding-carseries-10001-op-2'])


def test_page_03(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/tagManagement/library')
    # session_page.get_by_test_id('processing-2003').first.click()
    page_obj.pull_checked('library-10001', 'library-10001-1')
    page_obj.input('library-10005',
                   '啊USD化深度啊哈速度哈USD化深度啊哈速度啊哈速度啊厚度啊哈速度啊哈速度啊深度啊哈速度')


def test_page_04(session_page):
    """arco-checkbox arco-checkbox-indeterminate arco-checkbox arco-checkbox-checked"""
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/tagManagement/application')
    session_page.get_by_test_id('application-30001-b1-0').click()
    page_obj.checkbox('application-formform-item-10001',
                      ['application-formform-item-10002-0', 'application-formform-item-10002-1'], is_clear=True)
    page_obj.checkbox('application-formform-item-10008',
                      ['application-formform-item-10010-5', 'application-formform-item-10010-4'], is_clear=True)


def test_page_05(session_page):
    """arco-checkbox arco-checkbox-indeterminate arco-checkbox arco-checkbox-checked"""
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/settings/role')
    session_page.get_by_test_id('accountmanagement-20001-b1-0').click()
    page_obj.checkbox('mg-0-permission-g-b-t-b-check1-0',
                      ['mg-0-permission-g-b-t-b-check1-5', 'mg-0-permission-g-b-t-b-check1-1'], is_clear=True)
    # page_obj.checkbox('application-formform-item-10008', ['application-formform-item-10010-5','application-formform-item-10010-4'],is_clear=True)


def test_page_06(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('/ins/#/tagManagement/library')
    # session_page.get_by_test_id('library-list-20001-b1-0').click()
    # session_page.get_by_test_id('processing-2003').first.click()
    # page_obj.pull_cascade('library-form-10004', ['售后服务>click','服务流程>click','增值业务>click'])
    page_obj.button_click(text='查询')


def test_page_07(session_page):
    page_obj = PageHandleBase(session_page)
    session_page.goto('ins/#/dataCenter/monitor')
    page_obj.get_list_data('monitor-alarm-t1', 25)


def test_page_08(session_page):
    page_obj = PageHandleBase(session_page)
    page_obj.goto_local('accountmanagement-20001-b1-0', '/ins/#/settings/accountManagement')
    # page_obj.radio_select('account-form-10007-op-1', ['禁用'])
    # session_page.get_by_test_id('account-form-10008-op-1').locator('span').first.click()
    page_obj.time_input('account-form-10008-1', closing_date='2022-09-15', outer_testId='account-form-10008-op-1')
